﻿using CloudStorageLight.Core;
using CloudStorageLight.Core.Web;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CloudStorageLight.Core.Web
{
    [Serializable]
    public class BlobConfigurationItem
    {
        public string Command { get; set; }
        public string CurrentPath { get; set; }
        public string Path { get; set; }

        public string BlobType { get; set; }

        public string ConnectionString { get; set; }
        public string BlobContainerName { get; set; }

        public string SpSiteUrl { get; set; }
        public string DocumentLibraryName { get; set; }

        public string FtpUrl { get; set; }
        public string FtpFolderPath { get; set; }
        public bool Ftps { get; set; }

        public string FilePath { get; set; }
        public string FileShareName { get; set; }

        public string AccessToken { get; set; }
        public string RefreshToken { get; set; }
        public string AccessSecret { get; set; }
        public string StorageFolderPath { get; set; }

        public string User { get; set; }
        public string Password { get; set; }
        public string AuthMode { get; set; }

        public string Timezone { get; set; }

        public string EncryptKey { get; set; }

        public List<SelectListItem> TimezoneList
        {
            get 
            { 
                if (_TimezoneList == null)
                {
                    _TimezoneList = TimeZoneInfo.GetSystemTimeZones().Select(x => new SelectListItem { Value = x.Id, Text = x.DisplayName }).ToList(); 
                    _TimezoneList.Insert(0, new SelectListItem());
                }
                return _TimezoneList;
            }
        }private List<SelectListItem> _TimezoneList;

        public List<SelectListItem> AuthModeList
        {
            get
            {
                if (_authModeList == null)
                {
                    _authModeList = new List<SelectListItem>();
                    _authModeList.Add(new SelectListItem { Value="config", Text="configuration" });
                    _authModeList.Add(new SelectListItem { Value = "immediate", Text = "user input" });
                    _authModeList.Add(new SelectListItem { Value = "login", Text = "login credentials " });
                }
                return _authModeList;
            }
        }
        private List<SelectListItem> _authModeList;
    }

    [Serializable]
    public class BlobConfigurationAzureBlobItem : BlobConfigurationItem
    {
        public BlobConfigurationAzureBlobItem()
        {
            BlobType = "AzureBlob";
        }
    }

    [Serializable]
    public class BlobConfigurationSharePointDocLibItem : BlobConfigurationItem
    {
        public BlobConfigurationSharePointDocLibItem()
        {
            BlobType = "SharePointDocLib";
        }
    }

    [Serializable]
    public class BlobConfigurationAttachedSharePointDocLibItem : BlobConfigurationItem
    {
        public BlobConfigurationAttachedSharePointDocLibItem()
        {
            BlobType = "AttachedSharePoint";
            
        }
    }

    [Serializable]
    public class BlobConfigurationFtpItem : BlobConfigurationItem
    {
        public BlobConfigurationFtpItem()
        {
            BlobType = "FTP";
        }
    }

    [Serializable]
    public class BlobConfigurationFileItem : BlobConfigurationItem
    {
        public BlobConfigurationFileItem()
        {
            BlobType = "File";
        }
    }

    [Serializable]
    public class BlobConfigurationDropBoxItem : BlobConfigurationItem
    {
        public BlobConfigurationDropBoxItem()
        {
            BlobType = "DropBox";
        }
    }

    [Serializable]
    public class BlobConfigurationOneDriveItem : BlobConfigurationItem
    {
        public BlobConfigurationOneDriveItem()
        {
            BlobType = "OneDrive";
        }
    }

    [Serializable]
    public class BlobConfigurationGoogleDriveItem : BlobConfigurationItem
    {
        public BlobConfigurationGoogleDriveItem()
        {
            BlobType = "GoogleDrive";
        }
    }

    [Serializable]
    public class BlobConfigurationVM
    {

        public Dictionary<string, string> Types { get; set; }

        public List<BlobConfigurationItem> Items { get; set; }

        public List<SelectListItem> BlobTypeItems { get; set; }

        public BlobConfigurationVM()
        {
            Items = new List<BlobConfigurationItem>();

            Types = new Dictionary<string, string>();
            if (HttpContext.Current.Request.QueryString["SpHostUrl"] != null)
            {
                Types.Add("AttachedSharePoint", ViewMessages.MsgDocumentLibrary);
            }
            Types.Add("AzureBlob", "Azure blob");
            Types.Add("SharePointDocLib", ViewMessages.MsgSharePointDocumentLibrary);

            Types.Add("FTP", "FTP Site");
            if (SystemSettings.Instance.CanUseFileBlobAdapter) Types.Add("File", "File share");
            Types.Add("DropBox", "DropBox");
            Types.Add("OneDrive", "OneDrive");
            Types.Add("GoogleDrive", "Google Drive");

            BlobTypeItems = Types.Select(x=> new SelectListItem {Text = x.Value, Value = x.Key}).ToList();
            
        }

        public BlobConfigurationVM(BlobContainerConfig config)
            : this()
        {
            if (config == null) return;

            if (config.ContainerTypeName == typeof(CompositeBlobContainer).FullName)
            {
                var data = new BlobConfigurationAzureBlobItem();
                data.BlobContainerName = config.Parameters[0];
                data.ConnectionString = config.Parameters[1];
                if (config.Parameters.Length > 2) data.Path = config.Parameters[2];
                if (string.IsNullOrEmpty(data.Path)) data.Path = "/";
                if (data.Path != "/" || !string.IsNullOrEmpty(data.BlobContainerName) || !string.IsNullOrEmpty(data.ConnectionString))
                {
                    Items.Add(data);
                }
                if (config.Children == null) return;
                foreach (var item in config.Children)
                {
                    if (item.Children != null && item.Children.Length > 0) throw new NotSupportedException("support only level 1 child");
                    var parameters = item.Parameters.ToList();
                    for (int i=0;i<10;i++) parameters.Add(null); //10個の追加のデフォルトパラメータまで有効

                    if (item.ContainerTypeName.StartsWith(typeof(AzureBlobAdapter).FullName)) 
                    {
                        var itemData = new BlobConfigurationAzureBlobItem();
                        itemData.Path = parameters[0];
                        itemData.BlobContainerName = parameters[1];
                        itemData.ConnectionString = parameters[2];
                        itemData.EncryptKey = parameters[3];
                        itemData.Timezone = parameters[4];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(SpsBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationSharePointDocLibItem();
                        itemData.Path = parameters[0];
                        itemData.SpSiteUrl = parameters[1];
                        itemData.User = parameters[2];
                        itemData.Password = parameters[3];
                        itemData.DocumentLibraryName = parameters[4];
                        itemData.Timezone = parameters[5];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(AttachedSharePointBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationAttachedSharePointDocLibItem();
                        itemData.Path = parameters[0];
                        itemData.SpSiteUrl = parameters[1];
                        itemData.DocumentLibraryName = parameters[2];
                        itemData.User = parameters[3];
                        itemData.Password = parameters[4];
                        itemData.Timezone = parameters[5];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(FtpBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationFtpItem();
                        itemData.Path = parameters[0];
                        itemData.FtpUrl = parameters[1];
                        itemData.User = parameters[2];
                        itemData.Password = parameters[3];
                        itemData.FtpFolderPath = parameters[4];
                        itemData.Ftps = bool.Parse(parameters[5]);
                        itemData.Timezone = parameters[6];
                        itemData.AuthMode = parameters[7];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(FileBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationFileItem();
                        itemData.Path = parameters[0];
                        itemData.FilePath = parameters[1];
                        itemData.FileShareName = parameters[2];
                        itemData.User = parameters[3];
                        itemData.Password = parameters[4];
                        itemData.Timezone = parameters[5];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(DropBoxBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationDropBoxItem();
                        itemData.Path = parameters[0];
                        itemData.AccessToken = parameters[1];
                        itemData.AccessSecret = parameters[2];
                        itemData.StorageFolderPath = parameters[3];
                        itemData.Timezone = parameters[4];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(OneDriveBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationOneDriveItem();
                        itemData.Path = parameters[0];
                        itemData.AccessToken = parameters[1];
                        itemData.RefreshToken = parameters[2];
                        itemData.StorageFolderPath = parameters[3];
                        itemData.Timezone = parameters[4];
                        Items.Add(itemData);
                    }
                    else if (item.ContainerTypeName.StartsWith(typeof(GoogleDriveBlobAdapter).FullName))
                    {
                        var itemData = new BlobConfigurationGoogleDriveItem();
                        itemData.Path = parameters[0];
                        itemData.AccessToken = parameters[1];
                        itemData.RefreshToken = parameters[2];
                        itemData.StorageFolderPath = parameters[3];
                        itemData.Timezone = parameters[4];
                        Items.Add(itemData);
                    }
                    else
                    {
                        throw new ArgumentException("invalid ContainerTypeName", "config");
                    }
                }

            }
            else if (config.ContainerTypeName == typeof(AzureBlobContainer).AssemblyQualifiedName)
            {
                var data = new BlobConfigurationAzureBlobItem();
                data.BlobContainerName = config.Parameters[0];
                data.ConnectionString = config.Parameters[1];
                if (config.Parameters.Length > 2) data.Path = config.Parameters[2];
                if (string.IsNullOrEmpty(data.Path)) data.Path = "/";
                Items.Add(data);
                if (config.Children != null && config.Children.Length > 0) throw new NotSupportedException("AzureBlobContainer can not have child");
            }
            else
            {
                throw new ArgumentException("invalid ContainerTypeName", "config");
            }
        }

        public BlobContainerConfig ToBlobContainerConfig()
        {
            Clean();
            if (Items == null || Items.Count == 0) return null;
            var root = Items.Where(x => x.Path == "/").FirstOrDefault();
            var config = new BlobContainerConfig();
            if (root != null && root.BlobType == "AzureBlob" && Items.Count() == 1)
            {
                config.ContainerTypeName = typeof(AzureBlobContainer).FullName;
                config.Parameters = new string[] { root.BlobContainerName, root.ConnectionString, root.Path };
            }
            else
            {
                config.ContainerTypeName = typeof(CompositeBlobContainer).FullName;
                if (root == null)
                {
                    config.Parameters = new string[] {"", "", "/" };
                }
                else
                {
                    config.Parameters = new string[] { root.BlobContainerName, root.ConnectionString, root.Path };
                }
                var list = new List<BlobContainerConfig>();
                foreach (var item in Items.Where(x=>!string.IsNullOrEmpty(x.Path) && !string.IsNullOrEmpty(x.BlobType)))
                {
                    if (item == root) continue;

                    if (item.BlobType == "AzureBlob")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(AzureBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.BlobContainerName, item.ConnectionString, item.EncryptKey, item.Timezone };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "SharePointDocLib")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(SpsBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.SpSiteUrl, item.User, item.Password, item.DocumentLibraryName, item.Timezone };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "AttachedSharePoint")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(AttachedSharePointBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.SpSiteUrl, item.DocumentLibraryName, item.User, item.Password, item.Timezone };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "FTP")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(FtpBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.FtpUrl, item.User, item.Password, item.FtpFolderPath, item.Ftps.ToString(), item.Timezone, item.AuthMode };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "File")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(FileBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.FilePath, item.FileShareName, item.User, item.Password, item.Timezone };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "DropBox")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(DropBoxBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.AccessToken, item.AccessSecret, item.StorageFolderPath, item.Timezone };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "OneDrive")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(OneDriveBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.AccessToken, item.RefreshToken, item.StorageFolderPath, item.Timezone };
                        list.Add(itemConfig);
                    }
                    else if (item.BlobType == "GoogleDrive")
                    {
                        var itemConfig = new BlobContainerConfig();
                        itemConfig.ContainerTypeName = typeof(GoogleDriveBlobAdapter).AssemblyQualifiedName;
                        itemConfig.Parameters = new string[] { item.Path, item.AccessToken, item.RefreshToken, item.StorageFolderPath, item.Timezone };
                        list.Add(itemConfig);
                    }
                }

                config.Children = list.ToArray();
            }
            return config;
        }

        public void Clean()
        {
            foreach (var item in Items.ToList())
            {
                if (string.IsNullOrEmpty(item.Path)) Items.Remove(item);
            }

        }

    }

}